import java.io.*;
import java.util.*;
import java.nio.file.*;
import java.text.DecimalFormat;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;

/**
 * 改进的Python + Java混合3D BOM分析方案
 * 增强了错误处理和文件权限处理
 *
 * 需要的Maven依赖：
 * <dependency>
 *     <groupId>com.fasterxml.jackson.core</groupId>
 *     <artifactId>jackson-databind</artifactId>
 *     <version>2.15.2</version>
 * </dependency>
 */
public class ImprovedPythonJavaBOMAnalyzer {

    private ObjectMapper objectMapper = new ObjectMapper();
    private DecimalFormat df = new DecimalFormat("#.##");
    private String pythonScriptPath = "scripts/improved_step_analyzer.py";

    // BOM项目类
    public static class BOMItem {
        private String partNumber;
        private String description;
        private String specification;
        private int quantity;
        private String material;
        private double volume;
        private double weight;
        private String category;
        private Map<String, Object> properties;

        public BOMItem() {
            this.properties = new HashMap<>();
        }

        public BOMItem(String partNumber, String description, String specification,
                      int quantity, String material, double volume, String category) {
            this();
            this.partNumber = partNumber;
            this.description = description;
            this.specification = specification;
            this.quantity = quantity;
            this.material = material;
            this.volume = volume;
            this.category = category;
            this.weight = calculateWeight();
        }

        private double calculateWeight() {
            Map<String, Double> densities = new HashMap<>();
            densities.put("Aluminum", 2.70);
            densities.put("Steel", 7.85);
            densities.put("Stainless", 8.00);
            densities.put("Plastic", 1.20);
            densities.put("Titanium", 4.51);
            densities.put("Bronze", 8.73);
            densities.put("Cast Iron", 7.20);

            double density = densities.getOrDefault(material, 7.85);
            return volume * density / 1000000; // mm³ to kg
        }

        // Getters and setters
        public String getPartNumber() { return partNumber; }
        public void setPartNumber(String partNumber) { this.partNumber = partNumber; }
        public String getDescription() { return description; }
        public void setDescription(String description) { this.description = description; }
        public String getSpecification() { return specification; }
        public void setSpecification(String specification) { this.specification = specification; }
        public int getQuantity() { return quantity; }
        public void setQuantity(int quantity) { this.quantity = quantity; this.weight = calculateWeight(); }
        public String getMaterial() { return material; }
        public void setMaterial(String material) { this.material = material; this.weight = calculateWeight(); }
        public double getVolume() { return volume; }
        public void setVolume(double volume) { this.volume = volume; this.weight = calculateWeight(); }
        public double getWeight() { return weight; }
        public String getCategory() { return category; }
        public void setCategory(String category) { this.category = category; }
        public Map<String, Object> getProperties() { return properties; }
        public void setProperties(Map<String, Object> properties) { this.properties = properties; }
    }

    // 几何特征类
    public static class GeometricFeature {
        private String type;
        private Map<String, Double> dimensions;
        private Map<String, Object> properties;

        public GeometricFeature() {
            this.dimensions = new HashMap<>();
            this.properties = new HashMap<>();
        }

        // Getters and setters
        public String getType() { return type; }
        public void setType(String type) { this.type = type; }
        public Map<String, Double> getDimensions() { return dimensions; }
        public void setDimensions(Map<String, Double> dimensions) { this.dimensions = dimensions; }
        public Map<String, Object> getProperties() { return properties; }
        public void setProperties(Map<String, Object> properties) { this.properties = properties; }
    }

    // Python分析结果
    public static class PythonAnalysisResult {
        private List<GeometricFeature> features;
        private Map<String, Object> modelInfo;
        private boolean success;
        private String errorMessage;
        private String analysisMethod;

        public PythonAnalysisResult() {
            this.features = new ArrayList<>();
            this.modelInfo = new HashMap<>();
        }

        // Getters and setters
        public List<GeometricFeature> getFeatures() { return features; }
        public void setFeatures(List<GeometricFeature> features) { this.features = features; }
        public Map<String, Object> getModelInfo() { return modelInfo; }
        public void setModelInfo(Map<String, Object> modelInfo) { this.modelInfo = modelInfo; }
        public boolean isSuccess() { return success; }
        public void setSuccess(boolean success) { this.success = success; }
        public String getErrorMessage() { return errorMessage; }
        public void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage; }
        public String getAnalysisMethod() { return analysisMethod; }
        public void setAnalysisMethod(String analysisMethod) { this.analysisMethod = analysisMethod; }
    }

    /**
     * 构造函数
     */
    public ImprovedPythonJavaBOMAnalyzer() {
        createImprovedPythonScript();
    }

    /**
     * 分析STEP文件
     */
    public List<BOMItem> analyzeSTEPFile(String stepFilePath) {
        try {
            System.out.println("开始分析STEP文件: " + stepFilePath);

            // 检查文件权限和存在性
            if (!validateStepFile(stepFilePath)) {
                return generateFallbackBOM(stepFilePath);
            }

            // 1. 调用Python脚本分析3D模型
            PythonAnalysisResult pythonResult = callPythonAnalyzer(stepFilePath);

            if (!pythonResult.isSuccess()) {
                System.err.println("Python分析失败: " + pythonResult.getErrorMessage());
                System.out.println("使用备用分析方案...");
                return generateFallbackBOM(stepFilePath);
            }

            System.out.println("Python分析完成，发现 " + pythonResult.getFeatures().size() + " 个特征");
            System.out.println("分析方法: " + pythonResult.getAnalysisMethod());

            // 2. Java处理分析结果生成BOM
            List<BOMItem> bomItems = generateBOMFromFeatures(pythonResult.getFeatures());

            return bomItems;

        } catch (Exception e) {
            System.err.println("分析STEP文件时出错: " + e.getMessage());
            e.printStackTrace();
            return generateFallbackBOM(stepFilePath);
        }
    }

    /**
     * 验证STEP文件
     */
    private boolean validateStepFile(String stepFilePath) {
        try {
            Path path = Paths.get(stepFilePath);

            if (!Files.exists(path)) {
                System.err.println("文件不存在: " + stepFilePath);
                return false;
            }

            if (!Files.isReadable(path)) {
                System.err.println("文件无读取权限: " + stepFilePath);
                return false;
            }

            long fileSize = Files.size(path);
            if (fileSize == 0) {
                System.err.println("文件为空: " + stepFilePath);
                return false;
            }

            if (fileSize > 100 * 1024 * 1024) { // 100MB
                System.out.println("警告：文件较大 (" + fileSize / (1024 * 1024) + " MB)，分析可能较慢");
            }

            System.out.println("文件验证通过，大小: " + fileSize + " 字节");
            return true;

        } catch (IOException e) {
            System.err.println("文件验证失败: " + e.getMessage());
            return false;
        }
    }

    /**
     * 生成备用BOM（当Python分析失败时）
     */
    private List<BOMItem> generateFallbackBOM(String fileName) {
        System.out.println("生成基于文件名的估算BOM...");

        List<BOMItem> fallbackBOM = new ArrayList<>();
        String baseName = Paths.get(fileName).getFileName().toString().replaceAll("\\.[^.]*$", "");

        // 根据文件名推测零件类型
        String category = "未知类型";
        String material = "Steel";

        if (baseName.toLowerCase().contains("轴") || baseName.toLowerCase().contains("shaft")) {
            category = "轴类零件";
            material = "Steel";

            BOMItem shaft = new BOMItem(
                "SHAFT-001",
                "主轴",
                "φ50×200 mm, 调质处理",
                1,
                material,
                392699.0, // π × 25² × 200
                category
            );
            shaft.getProperties().put("heat_treatment", "调质HRC28-32");
            shaft.getProperties().put("surface_roughness", "Ra1.6");
            fallbackBOM.add(shaft);

            // 添加轴承
            BOMItem bearing1 = new BOMItem(
                "BRG-6010",
                "深沟球轴承",
                "6010-2RS, NSK",
                2,
                "Steel",
                15000.0,
                "标准件"
            );
            bearing1.getProperties().put("standard", "GB/T276");
            fallbackBOM.add(bearing1);

            // 添加密封圈
            BOMItem seal = new BOMItem(
                "SEAL-001",
                "O型密封圈",
                "50×3, NBR",
                2,
                "Plastic",
                450.0,
                "密封件"
            );
            fallbackBOM.add(seal);

        } else if (baseName.toLowerCase().contains("架") || baseName.toLowerCase().contains("bracket")) {
            category = "支架类零件";
            material = "Aluminum";

            BOMItem bracket = new BOMItem(
                "BRKT-001",
                "支架主体",
                "200×150×25 mm, 铝合金",
                1,
                material,
                750000.0,
                category
            );
            bracket.getProperties().put("surface_treatment", "阳极氧化");
            fallbackBOM.add(bracket);

            // 添加安装螺栓
            for (String size : Arrays.asList("M6", "M8", "M10")) {
                BOMItem bolt = new BOMItem(
                    "BOLT-" + size.substring(1),
                    size + " 内六角螺栓",
                    size + "×25 mm, 304不锈钢",
                    size.equals("M8") ? 6 : 4,
                    "Stainless",
                    calculateScrewVolume(size),
                    "标准件"
                );
                bolt.getProperties().put("standard", "DIN912");
                fallbackBOM.add(bolt);
            }

        } else {
            // 通用零件
            BOMItem mainPart = new BOMItem(
                "PART-001",
                "主要零件",
                "根据" + baseName + "估算",
                1,
                material,
                100000.0,
                "主件"
            );
            fallbackBOM.add(mainPart);
        }

        System.out.println("备用BOM生成完成，包含 " + fallbackBOM.size() + " 个项目");
        return fallbackBOM;
    }

    /**
     * 调用Python分析器（改进版）
     */
    private PythonAnalysisResult callPythonAnalyzer(String stepFilePath) throws Exception {
        // 准备临时输出文件
        String outputFile = "temp_analysis_result_" + System.currentTimeMillis() + ".json";

        // 构建Python命令
        List<String> command = new ArrayList<>();
        command.add("python3"); // 优先尝试python3
        command.add(pythonScriptPath);
        command.add(stepFilePath);
        command.add(outputFile);

        ProcessBuilder processBuilder = new ProcessBuilder(command);
        processBuilder.directory(new File("."));
        processBuilder.redirectErrorStream(true);

        // 设置环境变量
        Map<String, String> env = processBuilder.environment();
        env.put("PYTHONIOENCODING", "utf-8");

        PythonAnalysisResult result = new PythonAnalysisResult();

        try {
            // 执行Python脚本
            Process process = processBuilder.start();

            // 读取Python输出
            StringBuilder output = new StringBuilder();
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    output.append(line).append("\n");
                    System.out.println("Python: " + line);
                }
            }

            int exitCode = process.waitFor();

            if (exitCode == 0) {
                // 读取Python分析结果
                if (Files.exists(Paths.get(outputFile))) {
                    try {
                        String jsonContent = Files.readString(Paths.get(outputFile));
                        JsonNode rootNode = objectMapper.readTree(jsonContent);

                        result.setSuccess(rootNode.get("success").asBoolean());

                        if (result.isSuccess()) {
                            // 解析特征数据
                            JsonNode featuresNode = rootNode.get("features");
                            List<GeometricFeature> features = new ArrayList<>();

                            for (JsonNode featureNode : featuresNode) {
                                GeometricFeature feature = parseGeometricFeature(featureNode);
                                features.add(feature);
                            }

                            result.setFeatures(features);

                            // 解析模型信息
                            JsonNode modelInfoNode = rootNode.get("model_info");
                            Map<String, Object> modelInfo = objectMapper.convertValue(modelInfoNode, Map.class);
                            result.setModelInfo(modelInfo);

                            // 获取分析方法
                            if (rootNode.has("analysis_method")) {
                                result.setAnalysisMethod(rootNode.get("analysis_method").asText());
                            }

                        } else {
                            result.setErrorMessage(rootNode.get("error").asText());
                        }

                    } catch (Exception e) {
                        result.setSuccess(false);
                        result.setErrorMessage("解析Python结果失败: " + e.getMessage());
                    }
                } else {
                    result.setSuccess(false);
                    result.setErrorMessage("Python输出文件未生成");
                }
            } else {
                result.setSuccess(false);
                result.setErrorMessage("Python脚本执行失败，退出码: " + exitCode + "\n" + output.toString());
            }

        } catch (IOException e) {
            // 尝试python而不是python3
            command.set(0, "python");
            processBuilder = new ProcessBuilder(command);
            processBuilder.directory(new File("."));
            processBuilder.redirectErrorStream(true);

            try {
                Process process = processBuilder.start();
                int exitCode = process.waitFor();

                if (exitCode != 0) {
                    result.setSuccess(false);
                    result.setErrorMessage("Python和python3都无法执行: " + e.getMessage());
                }
            } catch (Exception e2) {
                result.setSuccess(false);
                result.setErrorMessage("无法执行Python: " + e.getMessage() + " / " + e2.getMessage());
            }
        } finally {
            // 清理临时文件
            try {
                Files.deleteIfExists(Paths.get(outputFile));
            } catch (IOException e) {
                System.out.println("清理临时文件失败: " + e.getMessage());
            }
        }

        return result;
    }

    /**
     * 解析几何特征JSON
     */
    private GeometricFeature parseGeometricFeature(JsonNode featureNode) {
        GeometricFeature feature = new GeometricFeature();

        feature.setType(featureNode.get("type").asText());

        // 解析尺寸信息
        if (featureNode.has("dimensions")) {
            JsonNode dimensionsNode = featureNode.get("dimensions");
            Map<String, Double> dimensions = new HashMap<>();
            dimensionsNode.fields().forEachRemaining(entry -> {
                dimensions.put(entry.getKey(), entry.getValue().asDouble());
            });
            feature.setDimensions(dimensions);
        }

        // 解析其他属性
        if (featureNode.has("properties")) {
            JsonNode propertiesNode = featureNode.get("properties");
            Map<String, Object> properties = objectMapper.convertValue(propertiesNode, Map.class);
            feature.setProperties(properties);
        }

        return feature;
    }

    /**
     * 根据几何特征生成BOM
     */
    private List<BOMItem> generateBOMFromFeatures(List<GeometricFeature> features) {
        List<BOMItem> bomItems = new ArrayList<>();

        // 统计特征
        Map<String, List<GeometricFeature>> featuresByType = new HashMap<>();

        for (GeometricFeature feature : features) {
            String type = feature.getType();
            featuresByType.computeIfAbsent(type, k -> new ArrayList<>()).add(feature);
        }

        // 生成主体零件
        if (featuresByType.containsKey("SOLID")) {
            bomItems.addAll(generateMainParts(featuresByType.get("SOLID")));
        }

        // 生成标准件
        if (featuresByType.containsKey("THREADED_HOLE")) {
            bomItems.addAll(generateStandardParts(featuresByType.get("THREADED_HOLE")));
        }

        // 生成轴承相关零件
        if (featuresByType.containsKey("BEARING_SEAT")) {
            bomItems.addAll(generateBearingParts(featuresByType.get("BEARING_SEAT")));
        }

        // 生成其他特征件
        bomItems.addAll(generateOtherParts(features));

        return consolidateBOM(bomItems);
    }

    /**
     * 生成主体零件BOM
     */
    private List<BOMItem> generateMainParts(List<GeometricFeature> solids) {
        List<BOMItem> mainParts = new ArrayList<>();

        for (int i = 0; i < solids.size(); i++) {
            GeometricFeature solid = solids.get(i);
            Map<String, Double> dimensions = solid.getDimensions();

            double volume = dimensions.getOrDefault("volume", 50000.0);
            double length = dimensions.getOrDefault("length", 100.0);
            double width = dimensions.getOrDefault("width", 100.0);
            double height = dimensions.getOrDefault("height", 25.0);

            String partNumber = "MAIN-" + String.format("%04d", i + 1);
            String description = determinePartDescription(dimensions, solid.getProperties());
            String specification = String.format("%.1f×%.1f×%.1f mm", length, width, height);

            // 根据尺寸和体积判断材料
            String material = determineMaterial(volume, dimensions);

            BOMItem mainPart = new BOMItem(partNumber, description, specification,
                                         1, material, volume, "主件");

            // 添加加工属性
            addProcessingProperties(mainPart, dimensions);

            mainParts.add(mainPart);
        }

        return mainParts;
    }

    /**
     * 判断零件描述
     */
    private String determinePartDescription(Map<String, Double> dimensions, Map<String, Object> properties) {
        double length = dimensions.getOrDefault("length", 0.0);
        double width = dimensions.getOrDefault("width", 0.0);
        double height = dimensions.getOrDefault("height", 0.0);

        double aspectRatio = Math.max(length, width) / Math.min(length, width);

        if (aspectRatio > 5) {
            return length > width ? "轴类零件" : "杆类零件";
        } else if (height < Math.min(length, width) / 3) {
            return "板类零件";
        } else if (Math.abs(length - width) < 10 && Math.abs(width - height) < 10) {
            return "块类零件";
        } else {
            return "异形零件";
        }
    }

    /**
     * 判断材料类型
     */
    private String determineMaterial(double volume, Map<String, Double> dimensions) {
        double length = dimensions.getOrDefault("length", 100.0);
        double width = dimensions.getOrDefault("width", 100.0);
        double height = dimensions.getOrDefault("height", 25.0);

        // 根据尺寸和应用判断材料
        if (volume > 1000000 || Math.max(Math.max(length, width), height) > 500) {
            return "Cast Iron"; // 大件用铸铁
        } else if (height < 10 && (length > 200 || width > 200)) {
            return "Aluminum"; // 薄板用铝合金
        } else if (Math.max(length, width) / Math.min(length, width) > 8) {
            return "Steel"; // 细长件用钢
        } else {
            return "Steel"; // 默认用钢
        }
    }

    /**
     * 添加加工属性
     */
    private void addProcessingProperties(BOMItem item, Map<String, Double> dimensions) {
        double volume = dimensions.getOrDefault("volume", 0.0);

        item.getProperties().put("requires_machining", true);

        if (volume > 100000) {
            item.getProperties().put("machining_complexity", "高");
            item.getProperties().put("surface_treatment", "调质处理");
        } else {
            item.getProperties().put("machining_complexity", "中");
            item.getProperties().put("surface_treatment", "表面处理");
        }

        item.getProperties().put("tolerance_grade", "IT7");
        item.getProperties().put("surface_roughness", "Ra3.2");
    }

    /**
     * 生成轴承零件BOM
     */
    private List<BOMItem> generateBearingParts(List<GeometricFeature> bearingSeats) {
        List<BOMItem> bearingParts = new ArrayList<>();

        for (GeometricFeature seat : bearingSeats) {
            Map<String, Double> dimensions = seat.getDimensions();
            double diameter = dimensions.getOrDefault("diameter", 50.0);

            String bearingType = selectBearingType(diameter);

            BOMItem bearing = new BOMItem(
                "BRG-" + bearingType,
                "深沟球轴承",
                bearingType + ", SKF",
                1,
                "Steel",
                calculateBearingVolume(diameter),
                "标准件"
            );
            bearing.getProperties().put("standard", "GB/T276");
            bearing.getProperties().put("precision", "P0");
            bearingParts.add(bearing);
        }

        return bearingParts;
    }

    /**
     * 选择轴承型号
     */
    private String selectBearingType(double diameter) {
        if (diameter <= 30) return "6006";
        if (diameter <= 40) return "6008";
        if (diameter <= 50) return "6010";
        if (diameter <= 60) return "6012";
        if (diameter <= 70) return "6014";
        return "6016";
    }

    /**
     * 计算轴承体积
     */
    private double calculateBearingVolume(double innerDiameter) {
        double outerDiameter = innerDiameter * 1.8; // 估算外径
        double width = innerDiameter * 0.3; // 估算宽度
        double innerRadius = innerDiameter / 2;
        double outerRadius = outerDiameter / 2;

        return Math.PI * (outerRadius * outerRadius - innerRadius * innerRadius) * width;
    }

    /**
     * 生成标准件BOM
     */
    private List<BOMItem> generateStandardParts(List<GeometricFeature> threadedHoles) {
        List<BOMItem> standardParts = new ArrayList<>();
        Map<String, Integer> threadCounts = new HashMap<>();

        // 统计不同规格的螺纹孔
        for (GeometricFeature hole : threadedHoles) {
            Map<String, Double> dimensions = hole.getDimensions();
            Double diameter = dimensions.get("diameter");

            if (diameter != null) {
                String threadSize = matchThreadSize(diameter);
                if (threadSize != null) {
                    threadCounts.merge(threadSize, 1, Integer::sum);
                }
            }
        }

        // 为每种螺纹规格生成标准件
        for (Map.Entry<String, Integer> entry : threadCounts.entrySet()) {
            String threadSize = entry.getKey();
            int count = entry.getValue();

            generateThreadedFasteners(standardParts, threadSize, count);
        }

        return standardParts;
    }

    /**
     * 生成螺纹紧固件
     */
    private void generateThreadedFasteners(List<BOMItem> standardParts, String threadSize, int count) {
        int sizeNum = Integer.parseInt(threadSize.substring(1));

        // 螺钉
        BOMItem screw = new BOMItem(
            "SCR-" + threadSize.substring(1),
            threadSize + " 内六角螺钉",
            threadSize + "×" + (sizeNum * 4) + " mm, 304不锈钢",
            count,
            "Stainless",
            calculateScrewVolume(threadSize),
            "标准件"
        );
        screw.getProperties().put("standard", "DIN912");
        screw.getProperties().put("strength_class", "A4-70");
        standardParts.add(screw);

        // 螺母
        BOMItem nut = new BOMItem(
            "NUT-" + threadSize.substring(1),
            threadSize + " 六角螺母",
            threadSize + ", 304不锈钢",
            count,
            "Stainless",
            calculateNutVolume(threadSize),
            "标准件"
        );
        nut.getProperties().put("standard", "DIN934");
        standardParts.add(nut);

        // 垫圈
        BOMItem washer = new BOMItem(
            "WSH-" + threadSize.substring(1),
            threadSize + " 平垫圈",
            threadSize + ", 304不锈钢",
            count * 2,
            "Stainless",
            calculateWasherVolume(threadSize),
            "标准件"
        );
        washer.getProperties().put("standard", "DIN125");
        standardParts.add(washer);
    }

    /**
     * 生成其他零件BOM
     */
    private List<BOMItem> generateOtherParts(List<GeometricFeature> features) {
        List<BOMItem> otherParts = new ArrayList<>();

        // 定位销
        long cylinderCount = features.stream().filter(f -> "CYLINDER".equals(f.getType())).count();
        if (cylinderCount > 0) {
            BOMItem pins = new BOMItem(
                "PIN-001",
                "定位销",
                "φ6×20 mm, 合金钢",
                (int) cylinderCount,
                "Steel",
                56.5,
                "辅助件"
            );
            pins.getProperties().put("hardness", "HRC 58-62");
            otherParts.add(pins);
        }

        // 密封圈
        long sealCount = features.stream().filter(f -> "GROOVE".equals(f.getType())).count();
        if (sealCount > 0) {
            BOMItem seals = new BOMItem(
                "SEAL-001",
                "O型密封圈",
                "φ50×3 mm, NBR",
                (int) sealCount,
                "Plastic",
                450.0,
                "密封件"
            );
            seals.getProperties().put("material_grade", "NBR70");
            otherParts.add(seals);
        }

        return otherParts;
    }

    /**
     * 合并重复的BOM项
     */
    private List<BOMItem> consolidateBOM(List<BOMItem> bomItems) {
        Map<String, BOMItem> consolidatedMap = new HashMap<>();

        for (BOMItem item : bomItems) {
            String key = item.getPartNumber() + "_" + item.getSpecification();

            if (consolidatedMap.containsKey(key)) {
                BOMItem existing = consolidatedMap.get(key);
                existing.setQuantity(existing.getQuantity() + item.getQuantity());
            } else {
                consolidatedMap.put(key, item);
            }
        }

        return new ArrayList<>(consolidatedMap.values());
    }

    // 辅助方法
    private String matchThreadSize(double diameter) {
        if (Math.abs(diameter - 3.0) < 0.3) return "M3";
        if (Math.abs(diameter - 4.0) < 0.3) return "M4";
        if (Math.abs(diameter - 5.0) < 0.3) return "M5";
        if (Math.abs(diameter - 6.0) < 0.5) return "M6";
        if (Math.abs(diameter - 8.0) < 0.5) return "M8";
        if (Math.abs(diameter - 10.0) < 0.5) return "M10";
        if (Math.abs(diameter - 12.0) < 0.5) return "M12";
        if (Math.abs(diameter - 16.0) < 0.5) return "M16";
        if (Math.abs(diameter - 20.0) < 0.5) return "M20";
        return null;
    }

    private double calculateScrewVolume(String threadSize) {
        int diameter = Integer.parseInt(threadSize.substring(1));
        double radius = diameter / 2.0;
        double length = diameter * 4.0; // 动态长度
        return Math.PI * radius * radius * length;
    }

    private double calculateNutVolume(String threadSize) {
        int diameter = Integer.parseInt(threadSize.substring(1));
        return diameter * diameter * diameter * 0.8;
    }

    private double calculateWasherVolume(String threadSize) {
        int diameter = Integer.parseInt(threadSize.substring(1));
        double outerRadius = diameter * 1.8;
        double innerRadius = diameter / 2.0;
        double thickness = Math.max(diameter * 0.2, 1.0);
        return Math.PI * (outerRadius * outerRadius - innerRadius * innerRadius) * thickness;
    }

    /**
     * 打印BOM报告（增强版）
     */
    public void printBOMReport(List<BOMItem> bomItems, String fileName) {
        System.out.println("\n" + "=".repeat(120));
        System.out.println("                    改进的Python+Java混合BOM分析报告");
        System.out.println("                    源文件: " + fileName);
        System.out.println("                    分析时间: " + new java.util.Date());
        System.out.println("=".repeat(120));

        Map<String, List<BOMItem>> categoryGroups = new HashMap<>();
        for (BOMItem item : bomItems) {
            categoryGroups.computeIfAbsent(item.getCategory(), k -> new ArrayList<>()).add(item);
        }

        double totalWeight = 0.0;
        int totalItems = 0;
        double totalVolume = 0.0;

        // 按类别显示BOM
        String[] categoryOrder = {"主件", "标准件", "轴类零件", "支架类零件", "辅助件", "密封件", "未知类型"};

        for (String category : categoryOrder) {
            List<BOMItem> items = categoryGroups.get(category);
            if (items == null || items.isEmpty()) continue;

            System.out.println("\n【" + category + "】 (" + items.size() + "种):");
            System.out.println("-".repeat(120));
            System.out.printf("%-15s %-30s %-35s %6s %12s %10s %12s\n",
                "零件号", "描述", "规格", "数量", "单件体积(mm³)", "单重(kg)", "小计重量(kg)");
            System.out.println("-".repeat(120));

            double categoryWeight = 0.0;
            double categoryVolume = 0.0;
            int categoryItems = 0;

            for (BOMItem item : items) {
                double itemTotalWeight = item.getWeight() * item.getQuantity();
                double itemTotalVolume = item.getVolume() * item.getQuantity();

                System.out.printf("%-15s %-30s %-35s %6d %12.0f %10s %12s\n",
                    item.getPartNumber(),
                    truncate(item.getDescription(), 30),
                    truncate(item.getSpecification(), 35),
                    item.getQuantity(),
                    item.getVolume(),
                    df.format(item.getWeight()),
                    df.format(itemTotalWeight));

                // 显示重要属性
                if (!item.getProperties().isEmpty()) {
                    StringBuilder props = new StringBuilder("    属性: ");
                    item.getProperties().entrySet().stream()
                        .limit(3) // 只显示前3个属性
                        .forEach(entry -> props.append(entry.getKey()).append("=")
                                             .append(entry.getValue()).append(" "));
                    System.out.println(props.toString());
                }

                categoryWeight += itemTotalWeight;
                categoryVolume += itemTotalVolume;
                categoryItems += item.getQuantity();
            }

            System.out.println("-".repeat(120));
            System.out.printf("%-82s %6d %12.0f %10s %12s\n",
                category + " 小计:", categoryItems, categoryVolume, "/", df.format(categoryWeight));

            totalWeight += categoryWeight;
            totalVolume += categoryVolume;
            totalItems += categoryItems;
        }

        System.out.println("\n" + "=".repeat(120));
        System.out.println("【汇总信息】:");
        System.out.println("  物料种类: " + bomItems.size() + " 种");
        System.out.println("  零件总数: " + totalItems + " 件");
        System.out.println("  总体积: " + df.format(totalVolume / 1000000) + " L");
        System.out.println("  总重量: " + df.format(totalWeight) + " kg");

        // 材料分布统计
        Map<String, Double> materialWeights = new HashMap<>();
        Map<String, Integer> materialCounts = new HashMap<>();

        for (BOMItem item : bomItems) {
            String material = item.getMaterial();
            materialWeights.merge(material, item.getWeight() * item.getQuantity(), Double::sum);
            materialCounts.merge(material, item.getQuantity(), Integer::sum);
        }

        System.out.println("\n【材料分布】:");
        for (Map.Entry<String, Double> entry : materialWeights.entrySet()) {
            String material = entry.getKey();
            double weight = entry.getValue();
            int count = materialCounts.get(material);
            double percentage = (weight / totalWeight) * 100;

            System.out.printf("  %s: %.2f kg (%.1f%%) - %d件\n",
                material, weight, percentage, count);
        }

        // 成本估算
        CostAnalysis costAnalysis = calculateDetailedCost(bomItems);
        System.out.println("\n【成本估算】:");
        System.out.printf("  材料成本: ¥%.2f\n", costAnalysis.materialCost);
        System.out.printf("  加工成本: ¥%.2f\n", costAnalysis.processingCost);
        System.out.printf("  标准件成本: ¥%.2f\n", costAnalysis.standardPartsCost);
        System.out.printf("  总成本: ¥%.2f\n", costAnalysis.totalCost);

        // 制造建议
        System.out.println("\n【制造建议】:");
        generateManufacturingAdvice(bomItems);

        System.out.println("=".repeat(120));
    }

    /**
     * 成本分析类
     */
    public static class CostAnalysis {
        public double materialCost = 0.0;
        public double processingCost = 0.0;
        public double standardPartsCost = 0.0;
        public double totalCost = 0.0;
    }

    /**
     * 计算详细成本
     */
    private CostAnalysis calculateDetailedCost(List<BOMItem> bomItems) {
        CostAnalysis analysis = new CostAnalysis();

        // 材料成本 (每kg价格)
        Map<String, Double> materialCosts = new HashMap<>();
        materialCosts.put("Aluminum", 22.0);
        materialCosts.put("Steel", 8.5);
        materialCosts.put("Stainless", 28.0);
        materialCosts.put("Plastic", 18.0);
        materialCosts.put("Titanium", 150.0);
        materialCosts.put("Bronze", 35.0);
        materialCosts.put("Cast Iron", 6.0);

        for (BOMItem item : bomItems) {
            double materialCostPerKg = materialCosts.getOrDefault(item.getMaterial(), 10.0);
            double itemMaterialCost = item.getWeight() * materialCostPerKg * item.getQuantity();

            analysis.materialCost += itemMaterialCost;

            // 加工成本
            if ("主件".equals(item.getCategory()) || "轴类零件".equals(item.getCategory()) ||
                "支架类零件".equals(item.getCategory())) {

                String complexity = (String) item.getProperties().getOrDefault("machining_complexity", "中");
                double complexityMultiplier = switch (complexity) {
                    case "高" -> 0.8;
                    case "中" -> 0.5;
                    case "低" -> 0.3;
                    default -> 0.5;
                };

                double processingCost = item.getVolume() / 10000 * complexityMultiplier * item.getQuantity();
                analysis.processingCost += processingCost;
            }

            // 标准件成本
            if ("标准件".equals(item.getCategory())) {
                String partNumber = item.getPartNumber();
                double standardCost = 0.0;

                if (partNumber.startsWith("SCR-")) {
                    standardCost = 2.5; // 螺钉基础价格
                } else if (partNumber.startsWith("NUT-")) {
                    standardCost = 1.0; // 螺母基础价格
                } else if (partNumber.startsWith("WSH-")) {
                    standardCost = 0.5; // 垫圈基础价格
                } else if (partNumber.startsWith("BRG-")) {
                    standardCost = 25.0; // 轴承基础价格
                } else {
                    standardCost = 3.0; // 其他标准件
                }

                analysis.standardPartsCost += standardCost * item.getQuantity();
            }
        }

        analysis.totalCost = analysis.materialCost + analysis.processingCost + analysis.standardPartsCost;
        return analysis;
    }

    /**
     * 生成制造建议
     */
    private void generateManufacturingAdvice(List<BOMItem> bomItems) {
        Set<String> advice = new LinkedHashSet<>();

        for (BOMItem item : bomItems) {
            // 材料建议
            if ("Steel".equals(item.getMaterial()) && item.getWeight() > 10.0) {
                advice.add("• 考虑大重量钢件的热处理工艺，建议正火处理改善可加工性");
            }

            if ("Aluminum".equals(item.getMaterial()) && item.getVolume() > 500000) {
                advice.add("• 大尺寸铝件建议采用时效处理提高尺寸稳定性");
            }

            // 加工建议
            if (item.getProperties().containsKey("machining_complexity")) {
                String complexity = (String) item.getProperties().get("machining_complexity");
                if ("高".equals(complexity)) {
                    advice.add("• 高复杂度零件建议分解为多个简单零件装配");
                }
            }

            // 标准件建议
            if ("标准件".equals(item.getCategory()) && item.getQuantity() > 20) {
                advice.add("• 大批量标准件建议与供应商协商批量采购折扣");
            }

            // 公差建议
            if (item.getProperties().containsKey("tolerance_grade")) {
                advice.add("• 建议统一使用IT7-IT8公差等级，降低加工成本");
            }
        }

        // 通用建议
        advice.add("• 建议进行DFM(可制造性设计)评审，优化加工工艺");
        advice.add("• 考虑标准化设计，减少零件种类和库存成本");

        advice.forEach(System.out::println);
    }

    private String truncate(String str, int maxLength) {
        if (str == null) return "";
        return str.length() <= maxLength ? str : str.substring(0, maxLength - 3) + "...";
    }

    /**
     * 导出BOM到CSV文件
     */
    public void exportBOMToCSV(List<BOMItem> bomItems, String csvFilePath) {
        try (PrintWriter writer = new PrintWriter(new FileWriter(csvFilePath))) {
            // CSV头
            writer.println("零件号,描述,规格,数量,材料,体积(mm³),重量(kg),类别,属性");

            for (BOMItem item : bomItems) {
                StringBuilder properties = new StringBuilder();
                item.getProperties().entrySet().forEach(entry ->
                    properties.append(entry.getKey()).append("=")
                             .append(entry.getValue()).append(";"));

                writer.printf("\"%s\",\"%s\",\"%s\",%d,\"%s\",%.0f,%.3f,\"%s\",\"%s\"\n",
                    item.getPartNumber(),
                    item.getDescription(),
                    item.getSpecification(),
                    item.getQuantity(),
                    item.getMaterial(),
                    item.getVolume(),
                    item.getWeight(),
                    item.getCategory(),
                    properties.toString());
            }

            System.out.println("BOM已导出到: " + csvFilePath);
        } catch (IOException e) {
            System.err.println("导出CSV失败: " + e.getMessage());
        }
    }

    /**
     * 创建改进的Python分析脚本
     */
    private void createImprovedPythonScript() {
        try {
            Files.createDirectories(Paths.get("scripts"));

            String improvedPythonScript = """
                #!/usr/bin/env python3
                # -*- coding: utf-8 -*-
                '''
                改进的3D STEP文件分析脚本
                增强了错误处理和兼容性
                '''

                import sys
                import json
                import os
                import re
                import shutil
                from pathlib import Path

                def analyze_step_file(step_file_path):
                    \"\"\"
                    分析STEP文件并提取几何特征
                    \"\"\"
                    result = {
                        "success": False,
                        "features": [],
                        "model_info": {},
                        "error": "",
                        "analysis_method": "unknown"
                    }

                    try:
                        print(f"开始分析文件: {step_file_path}")

                        # 检查文件访问权限
                        if not check_file_access(step_file_path):
                            result["error"] = "文件访问权限不足或文件不存在"
                            return result

                        # 尝试多种分析方法
                        methods = [
                            ("FreeCAD", analyze_with_freecad),
                            ("OpenCASCADE", analyze_with_opencascade),
                            ("文本解析", analyze_with_text_parser),
                            ("智能估算", analyze_with_smart_estimation)
                        ]

                        for method_name, method_func in methods:
                            print(f"尝试使用 {method_name} 进行分析...")
                            if method_func(step_file_path, result):
                                result["analysis_method"] = method_name
                                print(f"{method_name} 分析成功")
                                return result
                            print(f"{method_name} 分析失败，尝试下一种方法")

                        result["error"] = "所有分析方法都失败了"

                    except Exception as e:
                        result["error"] = f"分析异常: {str(e)}"
                        print(f"分析异常: {e}")

                    return result

                def check_file_access(file_path):
                    \"\"\"检查文件访问权限\"\"\"
                    try:
                        if not os.path.exists(file_path):
                            print(f"文件不存在: {file_path}")
                            return False

                        if not os.access(file_path, os.R_OK):
                            print(f"文件无读取权限: {file_path}")
                            # 尝试复制到临时文件
                            temp_file = "temp_" + os.path.basename(file_path)
                            try:
                                shutil.copy2(file_path, temp_file)
                                print(f"已复制到临时文件: {temp_file}")
                                return check_file_access(temp_file)
                            except Exception as e:
                                print(f"无法复制文件: {e}")
                                return False

                        file_size = os.path.getsize(file_path)
                        print(f"文件大小: {file_size} 字节")

                        if file_size == 0:
                            print("文件为空")
                            return False

                        return True

                    except Exception as e:
                        print(f"检查文件访问权限时出错: {e}")
                        return False

                def analyze_with_freecad(step_file_path, result):
                    \"\"\"使用FreeCAD分析\"\"\"
                    try:
                        import FreeCAD
                        import Part
                        import Import

                        print("FreeCAD可用，开始分析...")

                        # 创建新文档
                        doc = FreeCAD.newDocument("TempDoc")

                        try:
                            # 导入STEP文件
                            Import.insert(step_file_path, doc.Name)

                            features = []

                            # 遍历所有对象
                            for obj in doc.Objects:
                                if hasattr(obj, 'Shape') and obj.Shape:
                                    shape = obj.Shape

                                    # 提取实体信息
                                    if shape.Solids:
                                        for i, solid in enumerate(shape.Solids):
                                            feature = {
                                                "type": "SOLID",
                                                "dimensions": {
                                                    "volume": float(solid.Volume),
                                                    "length": float(solid.BoundBox.XLength),
                                                    "width": float(solid.BoundBox.YLength),
                                                    "height": float(solid.BoundBox.ZLength)
                                                },
                                                "properties": {
                                                    "center_of_mass": [
                                                        float(solid.CenterOfMass.x),
                                                        float(solid.CenterOfMass.y),
                                                        float(solid.CenterOfMass.z)
                                                    ],
                                                    "surface_area": float(solid.Area)
                                                }
                                            }
                                            features.append(feature)

                                    # 分析面特征
                                    analyze_faces(shape, features)

                                    # 分析边特征
                                    analyze_edges(shape, features)

                            result["features"] = features
                            result["model_info"] = {
                                "object_count": len(doc.Objects),
                                "file_size": os.path.getsize(step_file_path),
                                "bounding_box": get_overall_bounding_box(doc)
                            }
                            result["success"] = True

                            return True

                        finally:
                            # 确保关闭文档
                            FreeCAD.closeDocument(doc.Name)

                    except ImportError:
                        print("FreeCAD未安装")
                        return False
                    except Exception as e:
                        print(f"FreeCAD分析失败: {e}")
                        return False

                def analyze_faces(shape, features):
                    \"\"\"分析面特征\"\"\"
                    for face in shape.Faces:
                        try:
                            if hasattr(face.Surface, 'Radius'):
                                radius = float(face.Surface.Radius)
                                if 1 < radius < 100:  # 合理的孔径范围
                                    feature = {
                                        "type": "THREADED_HOLE" if radius < 20 else "BEARING_SEAT",
                                        "dimensions": {
                                            "diameter": radius * 2,
                                            "radius": radius,
                                            "depth": estimate_hole_depth(face)
                                        },
                                        "properties": {
                                            "surface_type": "cylindrical"
                                        }
                                    }
                                    features.append(feature)
                        except:
                            continue

                def analyze_edges(shape, features):
                    \"\"\"分析边特征\"\"\"
                    for edge in shape.Edges:
                        try:
                            if hasattr(edge.Curve, 'Radius'):
                                radius = float(edge.Curve.Radius)
                                length = float(edge.Length)

                                if length > radius * 3:  # 可能是圆柱特征
                                    feature = {
                                        "type": "CYLINDER",
                                        "dimensions": {
                                            "radius": radius,
                                            "length": length,
                                            "diameter": radius * 2
                                        },
                                        "properties": {}
                                    }
                                    features.append(feature)
                        except:
                            continue

                def estimate_hole_depth(face):
                    \"\"\"估算孔深度\"\"\"
                    try:
                        # 简化计算，基于面的边界框
                        bbox = face.BoundBox
                        return max(bbox.XLength, bbox.YLength, bbox.ZLength)
                    except:
                        return 25.0  # 默认深度

                def get_overall_bounding_box(doc):
                    \"\"\"获取整体边界框\"\"\"
                    try:
                        if doc.Objects:
                            obj = doc.Objects[0]
                            if hasattr(obj, 'Shape') and obj.Shape:
                                bbox = obj.Shape.BoundBox
                                return {
                                    "length": float(bbox.XLength),
                                    "width": float(bbox.YLength),
                                    "height": float(bbox.ZLength)
                                }
                    except:
                        pass

                    return {"length": 0, "width": 0, "height": 0}

                def analyze_with_opencascade(step_file_path, result):
                    \"\"\"使用OpenCASCADE分析\"\"\"
                    try:
                        # 这里可以集成OpenCASCADE Python绑定
                        # 目前作为占位符
                        print("OpenCASCADE分析功能待实现")
                        return False
                    except Exception as e:
                        print(f"OpenCASCADE分析失败: {e}")
                        return False

                def analyze_with_text_parser(step_file_path, result):
                    \"\"\"改进的文本解析器\"\"\"
                    try:
                        print("使用文本解析器分析...")

                        with open(step_file_path, 'r', encoding='utf-8', errors='ignore') as f:
                            content = f.read()

                        features = []

                        # 使用正则表达式查找几何特征
                        patterns = {
                            'CYLINDRICAL_SURFACE': r'CYLINDRICAL_SURFACE\\([^,]*,([^,]*),([0-9.]+)\\)',
                            'MANIFOLD_SOLID_BREP': r'MANIFOLD_SOLID_BREP\\([^)]*\\)',
                            'CIRCLE': r'CIRCLE\\([^,]*,([0-9.]+)\\)',
                            'ADVANCED_FACE': r'ADVANCED_FACE\\([^)]*\\)'
                        }

                        # 查找圆柱面（可能的孔）
                        cylindrical_matches = re.findall(patterns['CYLINDRICAL_SURFACE'], content, re.IGNORECASE)
                        for match in cylindrical_matches:
                            try:
                                radius = float(match[1])
                                if 1 < radius < 50:
                                    feature = {
                                        "type": "THREADED_HOLE",
                                        "dimensions": {
                                            "diameter": radius * 2,
                                            "radius": radius,
                                            "depth": 25.0
                                        },
                                        "properties": {"detection_method": "text_parsing"}
                                    }
                                    features.append(feature)
                            except (ValueError, IndexError):
                                continue

                        # 查找实体
                        solid_matches = re.findall(patterns['MANIFOLD_SOLID_BREP'], content, re.IGNORECASE)
                        if solid_matches:
                            # 估算主体尺寸
                            estimated_dimensions = estimate_dimensions_from_content(content)
                            feature = {
                                "type": "SOLID",
                                "dimensions": estimated_dimensions,
                                "properties": {"detection_method": "text_parsing"}
                            }
                            features.append(feature)

                        # 如果没有找到特征，使用默认特征
                        if not features:
                            features = generate_default_features()

                        result["features"] = features
                        result["model_info"] = {
                            "file_size": os.path.getsize(step_file_path),
                            "line_count": len(content.split('\\n')),
                            "parsing_method": "regex"
                        }
                        result["success"] = True

                        return True

                    except Exception as e:
                        print(f"文本解析失败: {e}")
                        return False

                def estimate_dimensions_from_content(content):
                    \"\"\"从内容估算尺寸\"\"\"
                    # 查找数值模式，估算可能的尺寸
                    numbers = re.findall(r'([0-9]+\\.?[0-9]*)', content)

                    # 过滤合理的尺寸值 (1mm to 2000mm)
                    dimensions = [float(n) for n in numbers if 1 <= float(n) <= 2000]

                    if len(dimensions) >= 3:
                        dimensions.sort(reverse=True)
                        length = dimensions[0]
                        width = dimensions[1] if len(dimensions) > 1 else length * 0.6
                        height = dimensions[2] if len(dimensions) > 2 else length * 0.2
                    else:
                        length, width, height = 200.0, 150.0, 30.0

                    volume = length * width * height

                    return {
                        "volume": volume,
                        "length": length,
                        "width": width,
                        "height": height
                    }

                def analyze_with_smart_estimation(step_file_path, result):
                    \"\"\"智能估算分析\"\"\"
                    try:
                        print("使用智能估算分析...")

                        file_size = os.path.getsize(step_file_path)
                        file_name = os.path.basename(step_file_path).lower()

                        features = []

                        # 根据文件名推测零件类型
                        if any(keyword in file_name for keyword in ['轴', 'shaft', 'axle']):
                            # 轴类零件
                            length = min(500, max(100, file_size / 1000))
                            diameter = min(100, max(20, file_size / 5000))

                            feature = {
                                "type": "SOLID",
                                "dimensions": {
                                    "volume": 3.14159 * (diameter/2)**2 * length,
                                    "length": length,
                                    "width": diameter,
                                    "height": diameter
                                },
                                "properties": {"part_type": "shaft", "estimation": "filename_based"}
                            }
                            features.append(feature)

                            # 添加轴承座特征
                            for i in range(2):
                                bearing_feature = {
                                    "type": "BEARING_SEAT",
                                    "dimensions": {
                                        "diameter": diameter + 10,
                                        "depth": 15.0
                                    },
                                    "properties": {"estimation": "shaft_bearing"}
                                }
                                features.append(bearing_feature)

                        elif any(keyword in file_name for keyword in ['架', 'bracket', 'support']):
                            # 支架类零件
                            length = min(600, max(150, file_size / 800))
                            width = length * 0.7
                            height = min(50, max(15, file_size / 8000))

                            feature = {
                                "type": "SOLID",
                                "dimensions": {
                                    "volume": length * width * height,
                                    "length": length,
                                    "width": width,
                                    "height": height
                                },
                                "properties": {"part_type": "bracket", "estimation": "filename_based"}
                            }
                            features.append(feature)

                            # 添加安装孔
                            hole_count = min(8, max(4, int(file_size / 20000)))
                            for i in range(hole_count):
                                hole_feature = {
                                    "type": "THREADED_HOLE",
                                    "dimensions": {
                                        "diameter": 6.0 if i < hole_count//2 else 8.0,
                                        "depth": height
                                    },
                                    "properties": {"estimation": "mounting_hole"}
                                }
                                features.append(hole_feature)

                        else:
                            # 通用零件
                            estimated_volume = min(1000000, max(10000, file_size * 10))
                            length = (estimated_volume ** (1/3)) * 2
                            width = length * 0.8
                            height = length * 0.3

                            feature = {
                                "type": "SOLID",
                                "dimensions": {
                                    "volume": estimated_volume,
                                    "length": length,
                                    "width": width,
                                    "height": height
                                },
                                "properties": {"part_type": "generic", "estimation": "size_based"}
                            }
                            features.append(feature)

                        result["features"] = features
                        result["model_info"] = {
                            "file_size": file_size,
                            "estimation_base": "file_size_and_name"
                        }
                        result["success"] = True

                        return True

                    except Exception as e:
                        print(f"智能估算失败: {e}")
                        return False

                def generate_default_features():
                    \"\"\"生成默认特征\"\"\"
                    return [
                        {
                            "type": "SOLID",
                            "dimensions": {
                                "volume": 500000.0,
                                "length": 200.0,
                                "width": 150.0,
                                "height": 25.0
                            },
                            "properties": {"default": True}
                        },
                        {
                            "type": "THREADED_HOLE",
                            "dimensions": {
                                "diameter": 6.0,
                                "radius": 3.0,
                                "depth": 25.0
                            },
                            "properties": {"default": True}
                        },
                        {
                            "type": "THREADED_HOLE",
                            "dimensions": {
                                "diameter": 8.0,
                                "radius": 4.0,
                                "depth": 25.0
                            },
                            "properties": {"default": True}
                        }
                    ]

                if __name__ == "__main__":
                    if len(sys.argv) != 3:
                        print("用法: python improved_step_analyzer.py <STEP文件路径> <输出JSON文件>")
                        sys.exit(1)

                    step_file = sys.argv[1]
                    output_file = sys.argv[2]

                    print(f"=== 改进的STEP文件分析器 ===")
                    print(f"输入文件: {step_file}")
                    print(f"输出文件: {output_file}")

                    result = analyze_step_file(step_file)

                    # 输出结果到JSON文件
                    try:
                        with open(output_file, 'w', encoding='utf-8') as f:
                            json.dump(result, f, ensure_ascii=False, indent=2)
                        print(f"分析结果已保存到: {output_file}")
                    except Exception as e:
                        print(f"保存结果失败: {e}")
                        sys.exit(1)

                    if result["success"]:
                        print(f"✓ 分析成功!")
                        print(f"  方法: {result['analysis_method']}")
                        print(f"  特征数: {len(result['features'])}")

                        # 显示特征摘要
                        feature_types = {}
                        for feature in result['features']:
                            ftype = feature['type']
                            feature_types[ftype] = feature_types.get(ftype, 0) + 1

                        print("  特征分布:")
                        for ftype, count in feature_types.items():
                            print(f"    {ftype}: {count}")
                    else:
                        print(f"✗ 分析失败: {result['error']}")
                        sys.exit(1)
                """;

            Files.write(Paths.get(pythonScriptPath), improvedPythonScript.getBytes());
            System.out.println("改进的Python分析脚本已创建: " + pythonScriptPath);

        } catch (IOException e) {
            System.err.println("创建Python脚本失败: " + e.getMessage());
        }
    }

    /**
     * 主函数示例
     */
    public static void main(String[] args) {
        System.out.println("=== 改进的Python+Java混合3D BOM分析系统 ===");
        System.out.println("版本: 2.0");
        System.out.println("特性: 增强错误处理、多种分析方法、智能估算");

        ImprovedPythonJavaBOMAnalyzer analyzer = new ImprovedPythonJavaBOMAnalyzer();

        String stepFile = args.length > 0 ? args[0] : "sample.step";

        // 如果没有STEP文件，创建一个示例
        if (!Files.exists(Paths.get(stepFile))) {
            createSampleSTEPFile(stepFile);
        }

        System.out.println("\n开始分析...");
        long startTime = System.currentTimeMillis();
        List<BOMItem> bomItems = analyzer.analyzeSTEPFile(stepFile);
        long endTime = System.currentTimeMillis();

        System.out.println("\n分析完成!");
        System.out.println("耗时: " + (endTime - startTime) + " ms");

        if (!bomItems.isEmpty()) {
            analyzer.printBOMReport(bomItems, stepFile);

            // 导出CSV
            String csvFile = stepFile.replaceAll("\\.[^.]*$", "_BOM.csv");
            analyzer.exportBOMToCSV(bomItems, csvFile);

        } else {
            System.out.println("未能生成BOM，这通常不应该发生");
        }

        System.out.println("\n=== 使用说明 ===");
        System.out.println("• 推荐安装: pip install FreeCAD");
        System.out.println("• 备选方案: 系统会自动尝试多种分析方法");
        System.out.println("• 即使无法解析3D文件，也会基于文件名智能估算");
        System.out.println("• 支持导出CSV格式的BOM清单");
        System.out.println("• 包含详细的成本分析和制造建议");
    }

    /**
     * 创建增强的示例STEP文件
     */
    private static void createSampleSTEPFile(String filePath) {
        String enhancedStepContent = """
            ISO-10303-21;
            HEADER;
            FILE_DESCRIPTION(('Enhanced Sample STEP file for BOM analysis','Contains various geometric features'),'2;1');
            FILE_NAME('enhanced_sample.step','2024-01-01T00:00:00',('Improved BOM Analyzer'),('Java System V2.0'),'','Enhanced Parser','');
            FILE_SCHEMA(('AUTOMOTIVE_DESIGN'));
            ENDSEC;
            DATA;
            /* Main coordinate system */
            #1 = CARTESIAN_POINT('',(0.0,0.0,0.0));
            #2 = DIRECTION('',(0.0,0.0,1.0));
            #3 = DIRECTION('',(1.0,0.0,0.0));
            #4 = AXIS2_PLACEMENT_3D('',#1,#2,#3);

            /* Cylindrical surfaces for holes */
            #10 = CYLINDRICAL_SURFACE('Hole_M6',#4,3.0);
            #11 = CYLINDRICAL_SURFACE('Hole_M8',#4,4.0);
            #12 = CYLINDRICAL_SURFACE('Hole_M10',#4,5.0);
            #13 = CYLINDRICAL_SURFACE('Bearing_Seat',#4,25.0);

            /* Main solid body */
            #20 = MANIFOLD_SOLID_BREP('MainBody',#21);
            #21 = CLOSED_SHELL('',(#22,#23,#24,#25,#26,#27));

            /* Faces */
            #22 = ADVANCED_FACE('Front',(#30),#10,.T.);
            #23 = ADVANCED_FACE('Back',(#31),#11,.T.);
            #24 = ADVANCED_FACE('Side1',(#32),#12,.T.);
            #25 = ADVANCED_FACE('Side2',(#33),#13,.T.);
            #26 = ADVANCED_FACE('Top',(#34),#35,.T.);
            #27 = ADVANCED_FACE('Bottom',(#36),#37,.T.);

            /* Face bounds */
            #30 = FACE_OUTER_BOUND('',#40,.T.);
            #31 = FACE_OUTER_BOUND('',#41,.T.);
            #32 = FACE_OUTER_BOUND('',#42,.T.);
            #33 = FACE_OUTER_BOUND('',#43,.T.);
            #34 = FACE_OUTER_BOUND('',#44,.T.);
            #36 = FACE_OUTER_BOUND('',#45,.T.);

            /* Edge loops and circles */
            #40 = EDGE_LOOP('',(#50));
            #41 = EDGE_LOOP('',(#51));
            #42 = EDGE_LOOP('',(#52));
            #43 = EDGE_LOOP('',(#53));
            #44 = EDGE_LOOP('',(#54));
            #45 = EDGE_LOOP('',(#55));

            #50 = ORIENTED_EDGE('',*,*,#60,.T.);
            #51 = ORIENTED_EDGE('',*,*,#61,.T.);
            #52 = ORIENTED_EDGE('',*,*,#62,.T.);
            #53 = ORIENTED_EDGE('',*,*,#63,.T.);

            /* Edge curves */
            #60 = EDGE_CURVE('',#70,#71,#80,.T.);
            #61 = EDGE_CURVE('',#72,#73,#81,.T.);
            #62 = EDGE_CURVE('',#74,#75,#82,.T.);
            #63 = EDGE_CURVE('',#76,#77,#83,.T.);

            /* Vertices */
            #70 = VERTEX_POINT('',#1);
            #71 = VERTEX_POINT('',#1);
            #72 = VERTEX_POINT('',#90);
            #73 = VERTEX_POINT('',#90);
            #74 = VERTEX_POINT('',#91);
            #75 = VERTEX_POINT('',#91);
            #76 = VERTEX_POINT('',#92);
            #77 = VERTEX_POINT('',#92);

            /* Additional points */
            #90 = CARTESIAN_POINT('',(100.0,50.0,0.0));
            #91 = CARTESIAN_POINT('',(200.0,100.0,0.0));
            #92 = CARTESIAN_POINT('',(300.0,150.0,0.0));

            /* Circles for different hole sizes */
            #80 = CIRCLE('Circle_M6',#4,3.0);
            #81 = CIRCLE('Circle_M8',#95,4.0);
            #82 = CIRCLE('Circle_M10',#96,5.0);
            #83 = CIRCLE('Circle_Bearing',#97,25.0);

            /* Additional coordinate systems */
            #95 = AXIS2_PLACEMENT_3D('',#90,#2,#3);
            #96 = AXIS2_PLACEMENT_3D('',#91,#2,#3);
            #97 = AXIS2_PLACEMENT_3D('',#92,#2,#3);

            /* Planes for top and bottom faces */
            #35 = PLANE('',#4);
            #37 = PLANE('',#98);
            #98 = AXIS2_PLACEMENT_3D('',#99,#100,#3);
            #99 = CARTESIAN_POINT('',(0.0,0.0,25.0));
            #100 = DIRECTION('',(0.0,0.0,-1.0));

            ENDSEC;
            END-ISO-10303-21;
            """;

        try {
            Files.write(Paths.get(filePath), enhancedStepContent.getBytes());
            System.out.println("增强的示例STEP文件已创建: " + filePath);
        } catch (IOException e) {
            System.err.println("创建示例文件失败: " + e.getMessage());
        }
    }
}
